﻿Imports DevExpress.XtraGrid.Views.Base
Imports System.Data

Public Class NavGridVGridPL
    Implements ISaveCommand, INewCommand

    Private WithEvents _aMetaDataTable As CommonExt.MetaDataTable
    Private WithEvents _aMetaDataTableChild As CommonExt.MetaDataTable
    Private WithEvents _aDataset As New DataSet("NavGridVGridPL")
    Private WithEvents _aview As Views.Grid.GridView

    Public Event InitDataExt(ByVal withChild As Boolean)
    Public Event ValidateDataExt()
    Public Event ProcessDataExt()
    Public Event SaveDataExt()
    Public Event DeleteDataExt()

    Public Property DataSet() As DataSet Implements ISaveCommand.Dataset
        Get
            Return _aDataset
        End Get
        Set(ByVal value As DataSet)
            _aDataset = value
        End Set
    End Property

    Public Property Pl() As PL.PLBase

    Public Property GridActionOptionList() As CommonExt.Base.ActionOptionList

    Public Property DefaultActionOptionList() As CommonExt.Base.ActionOptionList

    Public Property GridContextMenu() As GridViewMenu

    Public Property QueryName() As String
    ''' <summary>
    ''' Use to display column according to the security profile
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property SecureGrid() As Boolean = False

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.
        InitActionOption()
    End Sub

    Public Sub New(ByVal aQueryName As String)
        Me.New()
        QueryName = aQueryName
        ' Add any initialization after the InitializeComponent() call.
        InitGridExt()
    End Sub
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="withChild"></param>
    ''' <remarks>La grille essaye toujours d'avoir les enfants (by design)</remarks>
    Public Sub InitGridExt(Optional ByVal withChild As Boolean = True)
        'When you define "Event InitDataExt" VB.NET automatically adds a field call
        'InitDataExtEvent. The "InitDataExtEvent" will not show up in the IDE or Intellisense,
        'however you are free to use it in your code

        Dim colVisible As Boolean

        If Pl IsNot Nothing Then
            Pl.InitData(withChild)
            Me.DataSet = Pl.Dataset
        Else
            RaiseEvent InitDataExt(withChild)
        End If
        '_aDataset.Tables.Add(_aMetaDataTable)
        'Ici on se sert du parent de notre dataset
        'Par convention la table 0 de notre DataSet est le parent de nos relation
        Me.QueryName = _aDataset.Tables(0).TableName
        _aMetaDataTable = CType(_aDataset.Tables(0), MetaDataTable)
        GridControl1.DataSource = _aDataset.Tables(0)
        VGridControl1.DataSource = _aDataset.Tables(0)
        VGridControl1.RetrieveFields()
        'Pour chaque table du DataSet...
        For Each table As MetaDataTable In _aDataset.Tables
            'On regarde les relations de la table...(Les Enfants)
            For Each relation As DataRelation In table.ChildRelations
                Dim aView As GridView = New GridView(GridControl1)
                Dim Column As DevExpress.XtraGrid.Columns.GridColumn
                GridControl1.LevelTree.Nodes.Add(relation.RelationName, aView)

                'relation.ChildTable est un MetaDataTable, on construit nos DataSet avec des MetaDataTable.
                aView.PopulateColumns(relation.ChildTable)
                '
                'Ici on CTYPE relation.ChildTable car un DataRelation (un type du Framework de MS) contient des DataTable, 
                'comme notre MetaDataTable hérite d'un DataTable il est compatible

                Dim tableColumns As DataTable
                If SecureGrid Then
                    tableColumns = CommonExt.Base.AppManager.GetUserColumnSecurity(CType(relation.ChildTable, MetaDataTable).TableName, CommonExt.Base.AppManager.UserID)
                Else
                    tableColumns = CType(relation.ChildTable, MetaDataTable).MetaData
                End If

                '
                For Each arow As DataRow In tableColumns.Rows
                    colVisible = CBool(IIf(CInt(arow("pVisible")) = 0, False, True))
                    Column = aView.Columns(arow("ColumnName").ToString)
                    Column.VisibleIndex = CInt(arow("pOrder"))
                    Column.Caption = arow("pCaption").ToString
                    Column.Visible = colVisible
                    Column.Width = CInt(arow("pWidth"))
                    Column.OptionsColumn.AllowEdit = Not CBool(arow("pLocked"))
                Next
                aView.HorzScrollVisibility = ScrollVisibility.Always
                aView.OptionsDetail.EnableDetailToolTip = True
                aView.OptionsFilter.DefaultFilterEditorView = FilterEditorViewMode.VisualAndText
                aView.OptionsFilter.ShowAllTableValuesInFilterPopup = True
                aView.OptionsFilter.UseNewCustomFilterDialog = True
                aView.OptionsView.ColumnAutoWidth = False
                aView.OptionsView.NewItemRowPosition = DevExpress.XtraGrid.Views.Grid.NewItemRowPosition.Top
                aView.OptionsView.ShowAutoFilterRow = True
                aView.OptionsView.ShowChildrenInGroupPanel = True
                aView.OptionsSelection.MultiSelect = True
                aView.OptionsView.ShowFilterPanelMode = DevExpress.XtraGrid.Views.Base.ShowFilterPanelMode.ShowAlways
                'Make sure that the columns are define in the view before assignning LOV'S
                DevExGridHelper.AssignLKP(aView, CType(relation.ChildTable, MetaDataTable), Me.GridControl1)
            Next
        Next
        InitMainView()
        AssignLOV(_aMetaDataTable)
    End Sub

    ''' <summary>
    ''' Initialise la grille parents
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub InitMainView()
        Dim colVisible As Boolean
        Dim View As Views.Base.ColumnView = CType(GridControl1.MainView, ColumnView)
        Dim Column As DevExpress.XtraGrid.Columns.GridColumn

        Dim tableColumns As DataTable

        View.Columns.Clear()

        If SecureGrid Then
            tableColumns = CommonExt.Base.AppManager.GetUserColumnSecurity(_aMetaDataTable.TableName, CommonExt.Base.AppManager.UserID)
        Else
            tableColumns = _aMetaDataTable.MetaData
        End If

        For Each row As DataRow In tableColumns.Rows
            colVisible = CBool(IIf(CInt(row("pVisible")) = 0, False, True))
            Column = View.Columns.AddField(row("ColumnName").ToString)
            Column.VisibleIndex = CInt(row("pOrder"))
            Column.Caption = row("pCaption").ToString
            Column.Visible = colVisible
            Column.Width = CInt(row("pWidth"))
            Column.OptionsColumn.AllowEdit = Not CBool(row("pLocked"))
            Column.GroupIndex = CInt(row("pGroupByOrder"))

        Next

        GridView1.GridControl = Me.GridControl1
        GridView1.HorzScrollVisibility = DevExpress.XtraGrid.Views.Base.ScrollVisibility.Always
        GridView1.Name = "GridView1"
        GridView1.OptionsDetail.AllowExpandEmptyDetails = True
        GridView1.OptionsDetail.EnableDetailToolTip = True
        GridView1.OptionsFilter.DefaultFilterEditorView = DevExpress.XtraEditors.FilterEditorViewMode.VisualAndText
        GridView1.OptionsFilter.ShowAllTableValuesInFilterPopup = True
        GridView1.OptionsFilter.UseNewCustomFilterDialog = True
        GridView1.OptionsView.ShowAutoFilterRow = True
        GridView1.OptionsView.ShowChildrenInGroupPanel = True
        GridView1.OptionsView.ShowFilterPanelMode = DevExpress.XtraGrid.Views.Base.ShowFilterPanelMode.ShowAlways
        'Make sure that the columns are define in the view before assignning LOV'S
        AssignLOV(CType(View, GridView), _aMetaDataTable)

    End Sub

    Private Sub GridView1_InitNewRow(ByVal sender As Object, ByVal e As InitNewRowEventArgs) Handles GridView1.InitNewRow
        Dim view As GridView = CType(sender, GridView)
        view.SetRowCellValue(e.RowHandle, view.Columns(_aMetaDataTable.MetaCommand.GUIDField), System.Guid.NewGuid)
    End Sub

    Private Sub aView_InitNewRow(ByVal sender As Object, ByVal e As InitNewRowEventArgs) Handles _aview.InitNewRow
        Dim view As GridView = CType(sender, GridView)
        Dim drow As DataRow = view.GetFocusedDataRow()
        Dim table As MetaDataTable = CType(drow.Table, MetaDataTable)
        view.SetRowCellValue(e.RowHandle, view.Columns(table.MetaCommand.GUIDField), System.Guid.NewGuid)
    End Sub

    Public Function SaveCommand() As Boolean Implements CommonExt.ISaveCommand.SaveCommand
        Dim succesful As Boolean = True

        Try
            'Pour la grille de gauche
            GridControl1.FocusedView.CloseEditor()
            GridControl1.FocusedView.UpdateCurrentRow()
            '
            'Pour la grille vertical
            Me.VGridControl1.CloseEditor()
            Me.VGridControl1.UpdateFocusedRecord()
            '
            ' On Rafraichi la form
            Me.Refresh()
            If Not Me.DataSet.HasErrors Then
                If Pl IsNot Nothing Then
                    If Pl.Validate() Then
                        succesful = Pl.Save()
                        GridControl1.RefreshDataSource()
                    End If
                End If
            Else
                succesful = False
            End If
        Catch ex As Exception
            MessageWindow.ShowMessage(ex, MsgBoxStyle.Information)
        End Try
        Return succesful
    End Function
    ''' <summary>
    ''' Create a new row
    ''' </summary>
    ''' <remarks>Use Interface INewCommand, So we can call it from the Ribbon button New</remarks>
    Public Sub NewCommand() Implements CommonExt.INewCommand.NewCommand
        AddNewRow()
    End Sub
    Public Sub AddNewRow()
        GridView1.AddNewRow()
    End Sub

    Public Sub SaveDataSet()
        Try
            Dim table As MetaDataTable
            'TestPoint: Voir MetaDataTable pour les BuildCUDCommands, AssignAdapterCommandForCUD
            Dim DelDataSet As DataSet
            Dim AddDataSet As DataSet

            If Me.DataSet.HasChanges Then
                DelDataSet = Me.DataSet.GetChanges(DataRowState.Deleted)
                AddDataSet = Me.DataSet.GetChanges(DataRowState.Added Or DataRowState.Modified)
                If DelDataSet IsNot Nothing Then
                    For Each table In Me.DataSet.Tables
                        '1- applychanges to child Tables only for Deleted and Updated Rows  
                        For Each relation As DataRelation In table.ChildRelations
                            CType(relation.ChildTable, MetaDataTable).ApplyChanges(False, DelDataSet.Tables(relation.ChildTable.TableName))
                        Next
                        '2- Apply Changes on Parent tables
                        table.ApplyChanges(False)
                    Next
                End If

                'Save Added Record
                If AddDataSet IsNot Nothing Then
                    For Each table In Me.DataSet.Tables
                        '1- Save Parent 
                        table.ApplyChanges(False, AddDataSet.Tables(table.TableName))
                        For Each relation As DataRelation In table.ChildRelations
                            '2- Save Children
                            CType(relation.ChildTable, MetaDataTable).ApplyChanges(False, AddDataSet.Tables(relation.ChildTable.TableName))
                        Next
                    Next
                End If
                Me.DataSet.AcceptChanges()
            End If
        Catch sqlex As System.Data.SqlClient.SqlException
            _aDataset.RejectChanges()
            'HACK: On Utilise les codes de SQL. Attention si les codes change entre ADO et/ou SQL
            Select Case sqlex.Number
                Case 2601, 2627  'Unique Index/Constriant Violation
                    MessageWindow.ShowMessage("Record Already Exist, Operation Aborded", MsgBoxStyle.Information)
                    'On Rafraichie
                Case Else
                    MessageWindow.ShowMessage(String.Format("Database Error: {0} #{1} ", sqlex.Message, sqlex.Number), MsgBoxStyle.Information)
            End Select
        Catch dbcex As System.Data.DBConcurrencyException
            _aDataset.RejectChanges()
            MessageWindow.ShowMessage(String.Format("Concurrency Issue, Record Already Modified: {0}", dbcex.Message), MsgBoxStyle.Information)
        Catch ex As Exception
            _aDataset.RejectChanges()
            MessageWindow.ShowMessage(String.Format("Row Cannot Be Save: {0}. Make Sure You Have a CUD Command", ex.Message), MsgBoxStyle.Information)
        End Try
        GridControl1.RefreshDataSource()
    End Sub

    Private Sub AssignLOV(ByVal aView As GridView, ByVal aMetaDataTable As MetaDataTable)
        Dim aMetaquery As MetaQuery
        Dim colVisible As Boolean
        For Each lookup As KeyValuePair(Of String, Guid) In aMetaDataTable.ListOfLov
            'testPoint: Verify the GuidField in metaquery , The Guidfield is CASE sensitive, IE: ListvalueID is not equal to ListValueID
            aMetaquery = CommonExt.MetaQuery.GetMetaQueryById(lookup.Value)
            aMetaquery.FillResultQuery()
            'outstandingissue : will have to check the language and get the 2nd or 3thr column of LOV according to LOV Standard 
            Dim aLOV As New RepositoryItemGridLookUpEdit() With {.DataSource = aMetaquery.ResultQuery, .DisplayMember = aMetaquery.ResultQuery.Columns(3).ToString, .ValueMember = aMetaquery.GUIDField, .PopupFormSize = New Size(800, 300), .NullText = "(none)"}

            aLOV.View.HorzScrollVisibility = ScrollVisibility.Always
            aLOV.View.OptionsView.ColumnAutoWidth = False
            aLOV.View.OptionsView.ShowAutoFilterRow = True
            aLOV.View.OptionsBehavior.ReadOnly = True
            Dim View As Views.Base.ColumnView = aLOV.View
            Dim Column As DevExpress.XtraGrid.Columns.GridColumn
            View.Columns.Clear()
            For Each row As DataRow In aMetaquery.MetaColumns.Rows
                colVisible = CBool(IIf(CInt(row("pVisible")) = 0, False, True))
                Column = View.Columns.AddField(row("ColumnName").ToString)
                Column.VisibleIndex = CInt(row("pOrder"))
                Column.Caption = row("pCaption").ToString
                Column.Visible = colVisible
                Column.Width = CInt(row("pWidth"))
            Next

            ' bug de memoire
            'http://www.devexpress.com/Support/Center/p/B147229.aspx?searchtext=memory+leak&p=T4|P1|0
            Me.GridControl1.RepositoryItems.Add(aLOV)
            ' fin 

            aView.Columns(lookup.Key).ColumnEdit = aLOV
            aMetaquery.Dispose()
        Next
    End Sub

    Private Sub AssignLOV(ByVal aMetaDataTable As MetaDataTable)
        Dim aMetaquery As MetaQuery
        Dim colVisible As Boolean

        For Each lookup As KeyValuePair(Of String, Guid) In aMetaDataTable.ListOfLov
            'testPoint: Verify the GuidField in metaquery , The Guidfield is CASE sensitive, IE: ListvalueID is not equal to ListValueID
            aMetaquery = CommonExt.MetaQuery.GetMetaQueryById(lookup.Value)
            aMetaquery.FillResultQuery()
            'outstandingissue : will have to check the language and get the 2nd or 3thr column of LOV according to LOV Standard 
            Dim aLOV As New RepositoryItemGridLookUpEdit() With {.DataSource = aMetaquery.ResultQuery, .DisplayMember = aMetaquery.ResultQuery.Columns(3).ToString, .ValueMember = aMetaquery.GUIDField, .PopupFormSize = New Size(800, 300), .NullText = "(none)"}

            aLOV.View.HorzScrollVisibility = ScrollVisibility.Always
            aLOV.View.OptionsView.ColumnAutoWidth = False
            aLOV.View.OptionsView.ShowAutoFilterRow = True
            aLOV.View.OptionsBehavior.ReadOnly = True
            Dim View As Views.Base.ColumnView = aLOV.View
            Dim Column As DevExpress.XtraGrid.Columns.GridColumn
            View.Columns.Clear()
            For Each row As DataRow In aMetaquery.MetaColumns.Rows
                colVisible = CBool(IIf(CInt(row("pVisible")) = 0, False, True))
                Column = View.Columns.AddField(row("ColumnName").ToString)
                Column.VisibleIndex = CInt(row("pOrder"))
                Column.Caption = row("pCaption").ToString
                Column.Visible = colVisible
                Column.Width = CInt(row("pWidth"))
            Next
            'by Defualt Vgrid add prefix 'row'on column name when using 'retrivefield

            ' bug de memoire
            'http://www.devexpress.com/Support/Center/p/B147229.aspx?searchtext=memory+leak&p=T4|P1|0
            VGridControl1.RepositoryItems.Add(aLOV)
            '
            VGridControl1.Rows("row" & lookup.Key).Properties.RowEdit = aLOV
            aMetaquery.Dispose()
        Next
    End Sub


    Private Sub GridView1_MasterRowExpanded(ByVal sender As Object, ByVal e As DevExpress.XtraGrid.Views.Grid.CustomMasterRowEventArgs)
        _aview = TryCast(GridView1.GetDetailView(GridView1.FocusedRowHandle, 0), DevExpress.XtraGrid.Views.Grid.GridView)
    End Sub

    Private Sub GridControl1_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        ' checking if the end-user has right clicked the grid control 
        If e.Button = MouseButtons.Right Then
            DoShowMenu(GridView1.CalcHitInfo(New Point(e.X, e.Y)))
        End If
    End Sub

    Sub DoShowMenu(ByVal hi As DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitInfo)
        ' Create the menu. 
        Dim menu As DevExpress.XtraGrid.Menu.GridViewMenu = Nothing


        If hi.HitTest = Grid.ViewInfo.GridHitTest.RowIndicator Then
            GridContextMenu = New GridViewMenu(GridView1)
            Dim item As DXMenuItem

            If GridActionOptionList IsNot Nothing Then
                Dim grpName As String = String.Empty

                For Each action As CommonExt.Base.ActionOption In DefaultActionOptionList
                    item = New DXMenuItem(action.OptionTitle, action.EventHandler, Nothing)
                    item.Enabled = True
                    grpName = action.OptionGroup
                    GridContextMenu.Items.Add(item)
                Next


                'Add Action Option that need the grid DataRow
                For Each action As CommonExt.Base.ActionOption In Me.GridActionOptionList
                    item = New DXMenuItem(action.OptionTitle, action.EventHandler, Nothing)
                    item.Tag = GridView1.GetFocusedDataRow()
                    item.Enabled = action.Enabled
                    'item.Image = action.OptionIcon

                    If item.Tag Is Nothing Then
                        item.Enabled = False
                    End If

                    'Add new Group Separator when Group Name change
                    If (grpName <> action.OptionGroup And grpName <> String.Empty) Then
                        item.BeginGroup = True
                    End If

                    grpName = action.OptionGroup
                    GridContextMenu.Items.Add(item)
                Next

            End If

            'Display Menu
            GridContextMenu.Show(hi.HitPoint)
        End If
    End Sub

    Private Sub GridView1_ValidateRow(ByVal sender As System.Object, ByVal e As DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs)
        'HOWTO: Comment je peux appeler mon PL... de la table en question... - aleblanc

    End Sub

    Private Sub GridExt2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        InitGridExt()
    End Sub


    Private Sub InitActionOption()
        GridActionOptionList = New CommonExt.Base.ActionOptionList
        DefaultActionOptionList = New CommonExt.Base.ActionOptionList()

        Dim act As ActionOption = New CommonExt.Base.ActionOption("DefaultOption", "SaveData", "Save", AddressOf ContextMenuSave, True, True)
        GridActionOptionList.Add(act)

        act = New CommonExt.Base.ActionOption("DefaultOption", "DeleteData", "Delete", AddressOf ContextMenuDelete, True, True)
        GridActionOptionList.Add(act)

        act = New CommonExt.Base.ActionOption("DefaultOption", "VEdit", "V Edit", AddressOf ContextMenuVEdit, True, True)
        GridActionOptionList.Add(act)

        act = New CommonExt.Base.ActionOption("GridOption", "Refresh", "Refresh Data", AddressOf ContextMenuReloadGrid, True, True)
        DefaultActionOptionList.Add(act)

        act = New CommonExt.Base.ActionOption("GridOption", "ToExcel", "Export to Excel", AddressOf ContextMenuExportToExcel, True, True)
        DefaultActionOptionList.Add(act)

    End Sub

    Private Sub ContextMenuSave(ByVal sender As System.Object, ByVal e As EventArgs)
        Me.Cursor = Cursors.WaitCursor
        Me.SaveCommand()
        Me.Cursor = Cursors.Default
    End Sub

    Private Sub ContextMenuDelete(ByVal sender As System.Object, ByVal e As EventArgs)

    End Sub

    Private Sub ContextMenuVEdit(ByVal sender As System.Object, ByVal e As EventArgs)

    End Sub

    Private Sub ContextMenuExportToExcel(ByVal sender As System.Object, ByVal e As EventArgs)
        Try
            Dim filename As String = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), Me.QueryName + ".xls")
            GridView1.OptionsPrint.AutoWidth = False
            GridView1.ExportToXls(filename)

            MessageWindow.ShowMessage(String.Format("Export To Excel Succesfull.{0}{0}Your Filename is: {1}", vbCrLf, filename), MsgBoxStyle.Information)

        Catch ex As Exception
            Throw ex
        End Try
        Me.Cursor = Cursors.Default
    End Sub

    Private Sub ContextMenuReloadGrid(ByVal sender As System.Object, ByVal e As EventArgs)
        ReloadGrid()
    End Sub

    Public Sub ReloadGrid()
        Me.Cursor = Cursors.WaitCursor
        GridControl1.DataSource = Nothing
        '
        'On enleve les LOV et les editeurs de la grilles
        'Car pour les LOV on réutilise les colonnes qui on déjà le même LOV
        GridControl1.RepositoryItems.Clear()

        InitGridExt()
        Me.Cursor = Cursors.Default
    End Sub
End Class


